Micron Document
Fox's Git Mirrors


Displaying Raw • Download

examples/wasm/vendor/github.com/dunglas/httpsfv/displaystring.go 633735d797cc5f5d48cb2e22e8fd7cd743930daf (633735d7) Text, 2.08 KB

package httpsfv

import (
"encoding/hex"
"errors"
"strings"
"unicode"
"unicode/utf8"
)

type DisplayString string

var ErrInvalidDisplayString = errors.New("invalid display string type")

var notVcharOrSp = &unicode.RangeTable{
R16: []unicode.Range16{
{0x0000, 0x001f, 1},
{0x007f, 0x00ff, 1},
},
LatinOffset: 2,
}

// marshalSFV serializes as defined in
// https://httpwg.org/specs/rfc9651.html#ser-string.
func (s DisplayString) marshalSFV(b *strings.Builder) error {
if _, err := b.WriteString(\\`%"\\`); err != nil {
return err
}

for i := 0; i < len(s); i++ {
if s[i] == '%' || s[i] == '"' || unicode.Is(notVcharOrSp, rune(s[i])) {
b.WriteRune('%')
b.WriteString(hex.EncodeToString([]byte{s[i]}))

continue
}

b.WriteByte(s[i])
}

b.WriteByte('"')

return nil
}

// parseDisplayString parses as defined in
// https://httpwg.org/specs/rfc9651.html#parse-display.
func parseDisplayString(s *scanner) (DisplayString, error) {
if s.eof() || len(s.data[s.off:]) < 2 || s.data[s.off:2] != \\`%"\\` {
return "", &UnmarshalError{s.off, ErrInvalidDisplayString}
}
s.off += 2

var b strings.Builder
for !s.eof() {
c := s.data[s.off]
s.off++

switch c {
case '%':
if len(s.data[s.off:]) < 2 {
return "", &UnmarshalError{s.off, ErrInvalidDisplayString}
}
c0 := unhex(s.data[s.off])
if c0 == 0 {
return "", &UnmarshalError{s.off, ErrInvalidDisplayString}
}

c1 := unhex(s.data[s.off+1])
if c1 == 0 {
return "", &UnmarshalError{s.off, ErrInvalidDisplayString}
}

b.WriteByte(c0<<4 | c1)
s.off += 2
case '"':
r := b.String()
if !utf8.ValidString(r) {
return "", ErrInvalidDisplayString
}

return DisplayString(r), nil

default:
if unicode.Is(notVcharOrSp, rune(c)) {
return "", &UnmarshalError{s.off, ErrInvalidDisplayString}
}

b.WriteByte(c)
}
}

return "", &UnmarshalError{s.off, ErrInvalidDisplayString}
}

func unhex(c byte) byte {
switch {
case '0' <= c && c <= '9':
return c - '0'
case 'a' <= c && c <= 'f':
return c - 'a' + 10
default:
return 0
}
}

Served by rngit 1.5.2 - Generated in 0.02s